﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Help
{
    public class SoftKey
    {
        [DllImport("kernel32.dll")]
        public static extern int lstrlenA(string InString);
        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        public static extern void CopyStringToByte(byte[] pDest, string pSourceg, int ByteLenr);
        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        public static extern void CopyByteToString(StringBuilder pDest, byte[] pSource, int ByteLenr);

        //以下用于将16进制字符串转化为无符号长整型
        private uint HexToInt(string s)
        {
            string[] hexch = { "0", "1", "2", "3", "4", "5", "6", "7",
								       "8", "9", "A", "B", "C", "D", "E", "F"};
            s = s.ToUpper();
            int i, j;
            int r, n, k;
            string ch;

            k = 1; r = 0;
            for (i = s.Length; i > 0; i--)
            {
                ch = s.Substring(i - 1, 1);
                n = 0;
                for (j = 0; j < 16; j++)
                    if (ch == hexch[j])
                        n = j;
                r += (n * k);
                k *= 16;
            }
            return unchecked((uint)r);
        }


        public void EnCode(byte[] inb, byte[] outb, string Key)
        {

            UInt32 cnDelta, y, z, a, b, c, d, temp_2;
            UInt32[] buf = new UInt32[16];
            int n, i, nlen;
            UInt32 sum;
            //UInt32 temp, temp_1;
            string temp_string;


            cnDelta = 2654435769;
            sum = 0;

            nlen = Key.Length;
            i = 0;
            for (n = 1; n <= nlen; n = n + 2)
            {
                temp_string = Key.Substring(n - 1, 2);
                buf[i] = HexToInt(temp_string);
                i = i + 1;
            }
            a = 0; b = 0; c = 0; d = 0;
            for (n = 0; n <= 3; n++)
            {
                a = (buf[n] << (n * 8)) | a;
                b = (buf[n + 4] << (n * 8)) | b;
                c = (buf[n + 4 + 4] << (n * 8)) | c;
                d = (buf[n + 4 + 4 + 4] << (n * 8)) | d;
            }



            y = 0;
            z = 0;
            for (n = 0; n <= 3; n++)
            {
                temp_2 = inb[n];
                y = (temp_2 << (n * 8)) | y;
                temp_2 = inb[n + 4];
                z = (temp_2 << (n * 8)) | z;
            }


            n = 32;

            while (n > 0)
            {
                sum = cnDelta + sum;

                /*temp = (z << 4) & 0xFFFFFFFF;
                temp = (temp + a) & 0xFFFFFFFF;
                temp_1 = (z + sum) & 0xFFFFFFFF;
                temp = (temp ^ temp_1) & 0xFFFFFFFF;
                temp_1 = (z >> 5) & 0xFFFFFFFF;
                temp_1 = (temp_1 + b) & 0xFFFFFFFF;
                temp = (temp ^ temp_1) & 0xFFFFFFFF;
                temp = (temp + y) & 0xFFFFFFFF;
                y = temp & 0xFFFFFFFF;*/
                y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);

                /*temp = (y << 4) & 0xFFFFFFFF;
                temp = (temp + c) & 0xFFFFFFFF;
                temp_1 = (y + sum) & 0xFFFFFFFF;
                temp = (temp ^ temp_1) & 0xFFFFFFFF;
                temp_1 = (y >> 5) & 0xFFFFFFFF;
                temp_1 = (temp_1 + d) & 0xFFFFFFFF;
                temp = (temp ^ temp_1) & 0xFFFFFFFF;
                temp = (z + temp) & 0xFFFFFFFF;
                z = temp & 0xFFFFFFFF;*/
                z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
                n = n - 1;

            }

            for (n = 0; n <= 3; n++)
            {
                outb[n] = System.Convert.ToByte((y >> (n * 8)) & 255);
                outb[n + 4] = System.Convert.ToByte((z >> (n * 8)) & 255);
            }

        }

        public void DeCode(byte[] inb, byte[] outb, string Key)
        {

            UInt32 cnDelta, y, z, a, b, c, d, temp_2;
            UInt32[] buf = new UInt32[16];
            int n, i, nlen;
            UInt32 sum;
            //UInt32 temp, temp_1;
            string temp_string;


            cnDelta = 2654435769;
            sum = 0xC6EF3720;

            nlen = Key.Length;
            i = 0;
            for (n = 1; n <= nlen; n = n + 2)
            {
                temp_string = Key.Substring(n - 1, 2);
                buf[i] = HexToInt(temp_string);
                i = i + 1;
            }
            a = 0; b = 0; c = 0; d = 0;
            for (n = 0; n <= 3; n++)
            {
                a = (buf[n] << (n * 8)) | a;
                b = (buf[n + 4] << (n * 8)) | b;
                c = (buf[n + 4 + 4] << (n * 8)) | c;
                d = (buf[n + 4 + 4 + 4] << (n * 8)) | d;
            }



            y = 0;
            z = 0;
            for (n = 0; n <= 3; n++)
            {
                temp_2 = inb[n];
                y = (temp_2 << (n * 8)) | y;
                temp_2 = inb[n + 4];
                z = (temp_2 << (n * 8)) | z;
            }


            n = 32;

            while (n-- > 0)
            {
                z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
                y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
                sum -= cnDelta;

            }

            for (n = 0; n <= 3; n++)
            {
                outb[n] = System.Convert.ToByte((y >> (n * 8)) & 255);
                outb[n + 4] = System.Convert.ToByte((z >> (n * 8)) & 255);
            }

        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="InString"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        public string StrEnc(string InString)//使用增强算法，加密字符串
        {
            string Key = "99933E1FBB1119880622763E12A29999";
            byte[] b, outb;
            byte[] temp = new byte[8], outtemp = new byte[8];
            int n, i, nlen, outlen;
            string outstring;


            nlen = lstrlenA(InString) + 1;
            if (nlen < 8)
                outlen = 8;
            else
                outlen = nlen;
            b = new byte[outlen];
            outb = new byte[outlen];

            CopyStringToByte(b, InString, nlen);

            b.CopyTo(outb, 0);

            for (n = 0; n <= outlen - 8; n = n + 8)
            {
                for (i = 0; i < 8; i++) temp[i] = b[i + n];
                EnCode(temp, outtemp, Key);
                for (i = 0; i < 8; i++) outb[i + n] = outtemp[i];
            }

            outstring = "";
            for (n = 0; n <= outlen - 1; n++)
            {
                outstring = outstring + outb[n].ToString("X2");
            }
            return outstring;
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="InString"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        public string StrDec(string InString) //使用增强算法，解密字符串
        {
            string Key = "99933E1FBB1119880622763E12A29999";
            byte[] b, outb;
            byte[] temp = new byte[8], outtemp = new byte[8];
            int n, i, nlen, outlen;
            string temp_string;
            StringBuilder c_str;


            nlen = InString.Length;
            if (nlen < 16) outlen = 16;
            outlen = nlen / 2;
            b = new byte[outlen];
            outb = new byte[outlen];

            i = 0;
            for (n = 1; n <= nlen; n = n + 2)
            {
                temp_string = InString.Substring(n - 1, 2);
                b[i] = System.Convert.ToByte(HexToInt(temp_string));
                i = i + 1;
            }

            b.CopyTo(outb, 0);

            for (n = 0; n <= outlen - 8; n = n + 8)
            {
                for (i = 0; i < 8; i++) temp[i] = b[i + n];
                DeCode(temp, outtemp, Key);
                for (i = 0; i < 8; i++) outb[i + n] = outtemp[i];
            }

            c_str = new StringBuilder("", outlen);
            CopyByteToString(c_str, outb, outlen);
            return c_str.ToString();

        }

    }
}
